package com.threeox.commonlibrary.util.engine;

import android.content.Context;
import android.content.Intent;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;

import com.alibaba.fastjson.JSONObject;
import com.threeox.commonlibrary.config.CommonConfig;
import com.threeox.commonlibrary.entity.engine.model.layout.CommandMsg;
import com.threeox.commonlibrary.entity.engine.model.layout.ViewDataMsg;
import com.threeox.commonlibrary.util.CommonConstant.ModelViewType;
import com.threeox.commonlibrary.ui.view.inter.engine.model.IBaseViewControl;
import com.threeox.commonlibrary.ui.view.ModelButton;
import com.threeox.utillibrary.util.EmptyUtils;
import com.threeox.utillibrary.util.res.LayoutParamsUtils;
import com.threeox.utillibrary.util.res.LayoutUtils;
import com.threeox.utillibrary.util.LogUtils;
import com.threeox.utillibrary.util.res.IdHelper;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

/**
 *
 * @ClassName: ControlFactory
 *
 * @Description: Todo(ControlFactory 创造View 工厂)
 *
 * @author 赵屈犇
 *
 * @date 创建时间:2016/12/20 14:02 
 * 
 * @version 1.0
 */
public class ControlFactory {

    private static final String TAG = ControlFactory.class.getName();

    private LinearLayout mModelLayout, mCommandLayout;
    private Context mContext;

    private ControlFactory(LinearLayout modelLayout,LinearLayout commandLayout, Context context) {
        this.mCommandLayout = commandLayout;
        this.mModelLayout = modelLayout;
        this.mContext = context;
    }

    public static ControlFactory newInstance(LinearLayout modelLayout,LinearLayout commandLayout, Context context){
        return new ControlFactory(modelLayout, commandLayout, context);
    }

    /**
     * 填充View
     *
     * @param viewDataMsgs
     * @param intent
     */
    public void fillInView(List<ViewDataMsg> viewDataMsgs, Intent intent) {
        if (EmptyUtils.isNotEmpty(viewDataMsgs)) {
            for (ViewDataMsg viewMessage : viewDataMsgs) {
                String viewType = viewMessage.getViewType();
                if (ModelViewType.LAYOUTVIEW.equals(viewType)){ // 布局View
                    initLayout(viewMessage, intent, viewDataMsgs.size());
                } else if (ModelViewType.VIEWCLS.equals(viewType)){// 自定义view的Cls
                    initViewCls(viewMessage, intent);
                } else if (ModelViewType.LISTMODELVIEW.equals(viewType)){// list的模型驱动

                } else if (ModelViewType.ELSE.equals(viewType) || EmptyUtils.isEmpty(viewMessage.getViewType())){

                } else {
                    initViewControl(viewMessage, intent);
                }
            }
        }
    }

    /**
     * 填充命令按钮
     *
     * @param commandMsgs
     * @param onClick
     */
    public void fillInCommand(List<CommandMsg> commandMsgs, View.OnClickListener onClick) {
        if (EmptyUtils.isNotEmpty(commandMsgs)) {
            LinearLayout commandBox = null;
            for (int i = 0; i < commandMsgs.size(); i++) {
                CommandMsg commandMsg = commandMsgs.get(i);
                if (((i + 2) % 2) == 0) {
                    commandBox = getCommandLayout(mContext);
                    mCommandLayout.addView(commandBox);
                }
                commandBox.addView(new ModelButton(mContext).setCommandMsg(commandMsg, onClick));
            }
        } else {
            LogUtils.e(TAG, "没有填充按钮元素");
        }
    }

    /**
     * 初始化加载一个布局
     *
     * @param viewMessage
     * @param intent
     * @param length
     */
    private void initLayout(ViewDataMsg viewMessage, Intent intent, int length) {
        if (EmptyUtils.isNotEmpty(viewMessage.getLayoutId())){
            try {
                View view = LayoutUtils.inflate(mContext, viewMessage.getLayoutId());
                initPublicMethod(viewMessage, view, intent);
                mModelLayout.addView(view);
                if (length == 1) {// 如果只有个布局文件，就让他全屏
                    view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 初始化自定义ViewCls
     * 
     * @param viewMessage
     * @param intent
     */
    private void initViewCls(ViewDataMsg viewMessage, Intent intent) {
        try {
            Class viewCls = Class.forName(viewMessage.getViewCls());
            if (EmptyUtils.isNotEmpty(viewCls)){
                // 得到ViewCls 带有Context参数的构造方法
                Constructor<?> constructor = viewCls.getConstructor(Context.class);
                View view = (View) constructor.newInstance(mContext);
                initPublicMethod(viewMessage, view, intent);
                mModelLayout.addView(view);
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.e(TAG, "initViewCls报错了:"+e.getMessage());
        }
    }

    /**
     * 初始化ViewControl
     *
     * @param viewMsg
     * @param intent
     */
    private void initViewControl(ViewDataMsg viewMsg, Intent intent) {
        try {
            JSONObject viewControl1 = CommonConfig.getInstance().getViewControl();
            String viewClsName = viewControl1.getString(viewMsg.getViewType());
            if (EmptyUtils.isNotEmpty(viewClsName)){
                Class<?> viewCls = Class.forName(viewClsName);
                // 得到ViewCls 带有Context参数的构造方法
                Constructor<?> constructor = viewCls.getConstructor(Context.class);
                IBaseViewControl viewControl = (IBaseViewControl) constructor.newInstance(mContext);
                if (EmptyUtils.isNotEmpty(viewControl)) {
                    initPublicMethod(viewMsg, (View) viewControl, intent);
                    mModelLayout.addView((View) viewControl);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.e(TAG, "initViewControl报错了:"+e.getMessage());
        }
    }

    /**
     * 初始化公开的方法
     *
     * @param viewMessage
     * @param view
     * @param intent
     */
    private void initPublicMethod(ViewDataMsg viewMessage, View view, Intent intent) {
        try {
            view.setTag(viewMessage.getViewTag());//设置 TAG
            if (viewMessage.isShow()){
                view.setVisibility(View.VISIBLE);
            } else {// 隐藏View
                view.setVisibility(View.GONE);
            }
            JSONObject methods = viewMessage.initMethods(intent);
            initMethod(view, methods);// 反射调用方法
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.e(TAG, "initPublicMethod报错了:"+e.getMessage());
        }
    }

    /**
     * 反射方法
     *
     * @param obj
     * @param methods
     */
    private void initMethod(Object obj, JSONObject methods) {
        if (EmptyUtils.isNotEmpty(methods)) {
            Set<String> set = methods.keySet();
            Class<? extends Object> controlCls = obj.getClass();
            // 暂时只取本类的方法
            Method[] controlMethods = controlCls.getDeclaredMethods();
            for (String method : set) {
                if (method.contains(".")) {
                    String[] split = method.split("\\.");
                    if (obj instanceof View && split != null && split.length >= 2) {
                        String idStr = split[0];
                        View view= (View) obj;
                        Integer id = IdHelper.newInstance(mContext).getViewId(idStr);
                        if (EmptyUtils.isNotEmpty(id)) {
                            View subView = view.findViewById(id);
                            JSONObject subMethod = new JSONObject();
                            Object[] vals = methods.getObject(method, Object[].class);
                            subMethod.put(split[1], vals);
                            initMethod(subView, subMethod);
                        }
                    }
                } else {
                    Object[] vals = methods.getObject(method, Object[].class);
                    for (Method conMethod : controlMethods) {
                        String name = conMethod.getName();
                        if (name.equals(method)) {
                            try {
                                conMethod.invoke(obj, vals);
                            } catch (Exception e) {
                                LogUtils.e(method + "方法进行反射出错啦:" + e.getMessage());
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 得到命令按钮的布局
     *
     * @param context
     * @return
     */
    private static LinearLayout getCommandLayout(Context context) {
        android.widget.LinearLayout.LayoutParams params = LayoutParamsUtils.newInstance(context).getLinearLayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        LinearLayout layout = new LinearLayout(context);
        layout.setLayoutParams(params);
        layout.setOrientation(LinearLayout.HORIZONTAL);
        layout.setGravity(Gravity.CENTER_HORIZONTAL);
        return layout;
    }

}
